/*
 * Copyright (C) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "animator/animator.h"
#include "common/common.h"
#include <arkui/native_interface.h>
#include <cstdint>

namespace LottieTurbo {

Animator::~Animator()
{
    status_ = AnimatorStatus::END;
    Stop();
    OH_ArkUI_Animator_Cancel(animatorHandle_);
    if (animatorOption_ != nullptr) {
        OH_ArkUI_AnimatorOption_Dispose(animatorOption_);
        animatorOption_ = nullptr;
    }
    if (animateAPi_1_ != nullptr && animatorHandle_ != nullptr) {
        animateAPi_1_->disposeAnimator(animatorHandle_);
        animatorHandle_ = nullptr;
    }
}

int32_t Animator::SetDuration(int32_t duration)
{
    if (status_ == AnimatorStatus::END) {
        return -1;
    }
    if (animatorOption_ == nullptr) {
        DRAWING_LOGE("Animator::SetDuration failed, animatorOption_ Null");
        return -1;
    }
    int32_t eCode = 0;
    eCode = OH_ArkUI_AnimatorOption_SetDuration(animatorOption_, duration);
    if (eCode != 0) {
        DRAWING_LOGE("Animator::SetDuration: 启动animator动画%{public}d", eCode);
    }
    return eCode;
}

int32_t Animator::Play()
{
    if (status_ == AnimatorStatus::PLAY) {
        return ARKUI_ERROR_CODE_NO_ERROR;
    }
    if (animatorHandle_ == nullptr) {
        DRAWING_LOGE("Animator::Play failed, animatorHandle_ Null");
        return -1;
    }
    auto eCode = OH_ArkUI_Animator_Play(animatorHandle_);
    if (eCode != ARKUI_ERROR_CODE_NO_ERROR) {
        DRAWING_LOGE("Animator::Play failed, error code: %{public}d", eCode);
    }
    status_ = AnimatorStatus::PLAY;
    return eCode;
}

int32_t Animator::Pause()
{
    if (status_ == AnimatorStatus::PAUSE) {
        return ARKUI_ERROR_CODE_NO_ERROR;
    }
    if (animatorHandle_ == nullptr) {
        DRAWING_LOGE("Animator::Pause failed, animatorHandle_ Null");
        return -1;
    }
    auto eCode = OH_ArkUI_Animator_Pause(animatorHandle_);
    if (eCode != ARKUI_ERROR_CODE_NO_ERROR) {
        DRAWING_LOGE("Animator::Pause failed, error code: %{public}d", eCode);
    }
    status_ = AnimatorStatus::PAUSE;
    return eCode;
}

int32_t Animator::Stop()
{
    int32_t eCode = -1;
    if (status_ == AnimatorStatus::STOP) {
        return ARKUI_ERROR_CODE_NO_ERROR;
    }
    if (animatorHandle_ == nullptr) {
        DRAWING_LOGE("Animator::Stop failed, animatorHandle_ is nullptr");
        return eCode;
    }
    eCode = OH_ArkUI_Animator_Finish(animatorHandle_);
    if (eCode != ARKUI_ERROR_CODE_NO_ERROR) {
        DRAWING_LOGE("Animator::Stop failed, error code: %{public}d", eCode);
    }
    status_ = AnimatorStatus::STOP;
    return eCode;
}

const Animator::AnimatorStatus Animator::GetStatus() const
{
    return status_;
}

void Animator::SetFrameRateRange(ArkUI_ExpectedFrameRateRange frameRateRange)
{
    if (status_ == AnimatorStatus::END) {
        return;
    }
    frameRateRange_ = frameRateRange;
}

ArkUI_ExpectedFrameRateRange Animator::GetSetFrameRateRange() const
{
    return frameRateRange_;
}

int32_t Animator::UpdateFrameRateRange()
{
    int32_t eCode = -1;
    if (status_ == AnimatorStatus::END) {
        return eCode;
    }
    if (animatorHandle_ == nullptr) {
        DRAWING_LOGE("Animator::UpdateFrameRateRange failed, animatorHandle_ Null");
        return eCode;
    }
    if (animatorOption_ == nullptr) {
        DRAWING_LOGE("Animator::UpdateFrameRateRange failed, animatorOption_ Null");
        return -1;
    }
    eCode = OH_ArkUI_AnimatorOption_SetExpectedFrameRateRange(animatorOption_, &frameRateRange_);
    if (eCode != 0) {
        DRAWING_LOGE("\n\n\nAnimator::UpdateFrameRateRange: 设置animator动画帧率范围 错误代码%{public}d", eCode);
        return eCode;
    }
    eCode = OH_ArkUI_Animator_ResetAnimatorOption(animatorHandle_, animatorOption_);
    if (eCode != 0) {
        DRAWING_LOGE("\n\n\nAnimator::UpdateFrameRateRange: 设置animator动画帧率范围 重置option 错误代码%{public}d",
                     eCode);
        return eCode;
    }
    return eCode;
}

void Animator::Init(ArkUI_ContextHandle context)
{
    if (status_ != AnimatorStatus::IDLE) {
        return;
    }
    int32_t eCode = 0;
    // 创建ArkUI_AnimatorHandle
    animateAPi_1_ = reinterpret_cast<ArkUI_NativeAnimateAPI_1 *>(
        OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_ANIMATE, "ArkUI_NativeAnimateAPI_1"));
    if (animateAPi_1_ == nullptr) {
        DRAWING_LOGE("Animator::Init: AnimateAPi_1创建错误");
        return;
    }

    // 创建动画控制选项
    animatorOption_ = OH_ArkUI_AnimatorOption_Create(0);
    if (animatorOption_ == nullptr) {
        DRAWING_LOGE("Animator::Init OH_ArkUI_AnimatorOption_Create failed, animatorOption_ Null");
        return;
    }

    // 设置animator动画持续时间
    eCode = OH_ArkUI_AnimatorOption_SetDuration(animatorOption_, duration_);
    if (eCode != 0) {
        DRAWING_LOGE("\n\n\nAnimator::Init: 设置animator动画持续时间 错误代码%{public}d", eCode);
    }

    // 设置animator动画延迟时间
    eCode = OH_ArkUI_AnimatorOption_SetDelay(animatorOption_, delay_);
    if (eCode != 0) {
        DRAWING_LOGE("\n\n\nAnimator::Init: 设置animator动画期望延迟时间 错误代码%{public}d", eCode);
    }

    // 设置animator动画播放次数
    eCode = OH_ArkUI_AnimatorOption_SetIterations(animatorOption_, iterations_);
    if (eCode != 0) {
        DRAWING_LOGE("\n\n\nAnimator::Init: 设置animator动画播放次数 错误代码%{public}d", eCode);
    }

    // 设置animator动画遮罩
    eCode = OH_ArkUI_AnimatorOption_SetFill(animatorOption_, fill_);
    if (eCode != 0) {
        DRAWING_LOGE("\n\n\nAnimator::Init: 设置animator动画动画遮罩 错误代码%{public}d", eCode);
    }

    // 设置animator帧率范围
    this->UpdateFrameRateRange();

    // 设置animator 帧回调
    eCode = OH_ArkUI_AnimatorOption_RegisterOnFrameCallback(animatorOption_, this, OnCallBack);
    if (eCode != 0) {
        DRAWING_LOGE("\n\n\nAnimator::Init: 设置animator动画帧回调 错误代码%{public}d", eCode);
    }

    // 设置animator播放方向
    eCode = OH_ArkUI_AnimatorOption_SetDirection(animatorOption_, direction_);
    if (eCode != 0) {
        DRAWING_LOGE("\n\n\nAnimator::Init: 设置animator动画播放方向 错误代码%{public}d", eCode);
    }

    // 设置animator ArkUI_ContextHandle
    if (animateAPi_1_ != nullptr && animateAPi_1_->createAnimator != nullptr && context != nullptr) {
        animatorHandle_ = animateAPi_1_->createAnimator(context, animatorOption_);
    }
    status_ = AnimatorStatus::INIT;
}

void Animator::OnCallBack(ArkUI_AnimatorOnFrameEvent *event)
{
    void *res = OH_ArkUI_AnimatorOnFrameEvent_GetUserData(event);
    Animator *data = reinterpret_cast<Animator *>(res);
    if (data != nullptr && data->FunctionCallBack != nullptr) {
        data->FunctionCallBack();
    }
}

} // namespace LottieTurbo
